package emulator.hardware;

import java.io.PrintStream;
import java.util.Observer;

import emulator.EmulatorException;
import emulator.support.CpuState;

/** General CPU interface */
public interface CPU {
	/** resets chip 
	 * @throws EmulatorException */
	void reset() throws EmulatorException;
	/** raises interrupt 
	 * @throws EmulatorException */
	void irq() throws EmulatorException;
	/** raises non-mask-able interrupt 
	 * @throws EmulatorException */
	void nmi() throws EmulatorException;
	
	/** runs single step (runs for one command then stop) 
	 * @throws EmulatorException */
	void step() throws EmulatorException;
	/** runs single step (runs for one command or subroutine then stop) 
	 * @throws EmulatorException */
	void stepOver() throws EmulatorException;
	/** runs freely 
	 * @throws EmulatorException */
	void go() throws EmulatorException;
	/** stops execution */
	void halt();
	/** waits for stopped execution */
	void waitForHalt();
	/** adds observer for running state (boolean) */
	void addRunningStateObserver(Observer observer);
	
	/** Prints state to stdout 
	 * @throws EmulatorException */
	void printState(PrintStream out) throws EmulatorException;
	
	/** Sets event handler for CPU events */
	void setEventHandler(CPUEventHandler handler);
	/** Sets CPU instruction execution observer */
	void setExecutionObserver(CPUExecutionObserver observer);
	
	/** Sets/clears simple breakpoint */
	void breakAt(HwNumber address, boolean enable);
	/** Sets simple stop (break once) */
	void stopOnceAt(HwNumber address);
	/** Clears all stops (on time breaks & break on return) */
	void clearAllStops();
	/** Enables break on return (step out) */
	void enableBreakOnReturn(boolean enable);
	
	/** sets register value */
	void setValue(String name, int value);
	/** gets PC */
	int getPC();

	/** gets elapsed ticks */
	long getTicks();
	
	/** gets internal state information (registers) */
	CpuState getCpuState();
}
